#include "A6GSM.h"

#if defined(USE_SOFTWARE_SERIAL)
A6GSM::A6GSM(SoftwareSerial &next, uint32_t baud): GSM_Serial(&next)
{
  GSM_Serial->begin(baud);
  flushSerial();
}
#else
A6GSM::A6GSM(HardwareSerial &next, uint32_t baud): GSM_Serial(&next)
{
  GSM_Serial->begin(baud);
  flushSerial();
}
#endif

//Call Start
void A6GSM::Reset(const int rst, int on_time, int off_time)
{
	//Serial.println("GSM Resetting......");
	digitalWrite(rst, HIGH);
	delay(on_time);
	digitalWrite(rst, LOW);
	delay(off_time);
}//end Call

//Call Start
void A6GSM::Call(String phone_no)
{
  Serial.println("Calling from Arduino......");
  delay(2000);
  GSM_Serial->println("AT");
  delay(10000);
  GSM_Serial->print("ATD");
  GSM_Serial->println(phone_no);
  delay(20000);
  GSM_Serial->println("ATH");
  Serial.println("Call Ended.....");
  delay(500);
}//end Call

//SMS Start
void A6GSM::Send_SMS(String phone_no, String Data)
{
	Serial.println("SMS Sending from Arduino......");

    GSM_Serial->println("AT+CMGF=1");
    delay(500);
    GSM_Serial->println("AT+CMGS=\"" + phone_no + "\"");
	GSM_Serial->write(0x0D);
	GSM_Serial->write(0x0a);
    delay(2000);
    GSM_Serial->println(Data);
    delay(2000);
    GSM_Serial->write(26);
    GSM_Serial->print("\r\n");
    delay(1000);
	
	Serial.println("SMS Sent.......");
}//end SMS

//SMS_Read Start
String A6GSM::Read_SMS()
{
	Serial.println("SMS_Read Sending......");
	delay(1000);
	Serial.println("SMS_Read End......");
	delay(1000);
}//end SMS_Read

bool A6GSM::A6begin()
{
  GSM_Serial->println("AT+CREG?");
  byte net = A6waitFor("1,", "5,", 1500);  // 1: registered, home network ; 5: registered, roaming

  while ( net != OK)
  {
    GSM_Serial->println("AT+CREG?");
    net = A6waitFor("1,", "5,", 1500);
  }

  if (A6command("AT&F0", "OK", "yy", 5000, 2) == OK)  // Reset to factory settings
  {
    if (A6command("ATE0", "OK", "yy", 5000, 2) == OK)  // disable Echo
    {
      if (A6command("AT+CMEE=2", "OK", "yy", 5000, 2) == OK)
      {
        return OK;  // enable better error messages
      }
      else
      {
        return NOTOK;
      }
    }
  }
}

byte A6GSM::A6command(String command, String response1, String response2, int timeOut, int repetitions) 
{
  byte returnValue = NOTOK;
  byte count = 0;
  while (count < repetitions && returnValue != OK) 
  {
    GSM_Serial->println(command);
    //Serial.print("Command: ");
    //Serial.println(command);
    if (A6waitFor(response1, response2, timeOut) == OK) 
    {
      //     Serial.println("OK");
      returnValue = OK;
    } 
    else
    { 
      returnValue = NOTOK;
    }
    count++;
  }
  return returnValue;
}

String A6GSM::A6read() 
{
  String reply = "";
  if (GSM_Serial->available())  
  {
    reply = GSM_Serial->readString();
  }
  //  Serial.print("Reply: ");
  // Serial.println(reply);
  return reply;
}

byte A6GSM::A6waitFor(String response1, String response2, int timeOut) 
{
  unsigned long entry = millis();
  int count = 0;
  String reply = A6read();
  byte retVal = 9;
  do {
    reply = A6read();
    if (reply != "") 
    {
      //Serial.print((millis() - entry));
      //Serial.print(" ms ");
      Serial.println(reply);
      //ShowSerialData(reply);
    }
  } while ((reply.indexOf(response1) + reply.indexOf(response2) == -2) && millis() - entry < timeOut );
  if ((millis() - entry) >= timeOut) {
    retVal = TIMEOUT;
  } else {
    if (reply.indexOf(response1) + reply.indexOf(response2) > -2) retVal = OK;
    else retVal = NOTOK;
  }
  //  Serial.print("retVal = ");
  //  Serial.println(retVal);
  return retVal;
}

void A6GSM::request(String host, String Path, String data, String dev_ID)
{
  //Serial.print(data);
  A6command("AT+CIPSTART=\"TCP\",\"" + host + "\",80", "CONNECT OK", "yy", 5000, 1); //start up the connection
  A6command("AT+CIPSEND", ">", "yy", 8000, 1); //begin send data to remote server
  GSM_Serial->print("GET "+Path);
  GSM_Serial->print("?data=");
  GSM_Serial->print(data);
  GSM_Serial->print("&dev_id=");
  GSM_Serial->print(dev_ID);
  GSM_Serial->print(" HTTP/1.1");
  GSM_Serial->print("\r\n");
  GSM_Serial->print("HOST: ");
  GSM_Serial->print(host);
  GSM_Serial->print("\r\n");
  GSM_Serial->print("\r\n");
  A6command(end_c, "HTTP/1.1", "yy", 8000, 1); //begin send data to remote server
  A6command("AT+CIPCLOSE", "OK", "yy", 5000, 1); //sending
  delay(1000);
}

void A6GSM::network(String opt)
{
  Serial.println("GSM Network Setup");
  A6command("AT+EGMR=2,7", "OK", "yy", 10000, 1);
  A6command("AT+CSQ", "OK", "yy", 10000, 1);
  A6command("AT+CGATT=1", "OK", "yy", 10000, 1);
  //A6command("AT+CIPSTATUS", "OK", "yy", 10000, 1);
  A6command("AT+CGDCONT=1,\"IP\",\"" + opt +"\"", "OK", "yy", 10000, 1); //bring up wireless connection
  //A6command("AT+CIPSTATUS", "OK", "yy", 10000, 2);
  A6command("AT+CGACT=1,1", "OK", "yy",10000, 1);
  //A6command("AT+CIPSTATUS", "OK", "yy", 10000, 1);
  A6command("AT+CIFSR", "OK", "yy", 10000, 1);
  //A6command("AT+CIPSTATUS", "OK", "yy", 10000, 1);
}

String A6GSM::split_data(String inputString, String delimiter, String endChar) 
{
  String tempString = "";
  int from;
  int to;
  for (int i = 0; i < inputString.length(); i++) 
  {
    if (inputString.substring(i, i + 1) == delimiter) 
    {
      from = i + 1;
    }
    if (inputString.substring(i, i + 1) == endChar) 
    {
      to = i;
    }
  }
  tempString = inputString.substring(from, to);
  return tempString;
}

String A6GSM::splitdata(String data, char separator, int index)
{
  int found = 0;
  int strIndex[] = {0, -1};
  int maxIndex = data.length()-1;

  for(int i=0; i<=maxIndex && found<=index; i++)
  {
    if(data.charAt(i)==separator || i==maxIndex)
    {
        found++;
        strIndex[0] = strIndex[1]+1;
        strIndex[1] = (i == maxIndex) ? i+1 : i;
    }
  }
  return found>index ? data.substring(strIndex[0], strIndex[1]) : "";
}

void A6GSM::net_Init(const int rst, int on, int off, String opt)
{
	//Serial.println("Network Initilation.....");
	pinMode(rst, OUTPUT);
	
	Reset(rst, on, off);
	
	if (A6begin() != OK) 
	{
		Serial.println("Error");
		while (1 == 1);
	}
  
	network(opt);
}

void A6GSM::flushSerial()
{
  Serial.flush();
  GSM_Serial->flush();
}//end flush